package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.*;
import com.tanhua.model.domain.PageResult;
import com.tanhua.model.domain.Question;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.dto.RecommendUserDto;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.NearUserVo;
import com.tanhua.model.vo.TodayBest;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.ThreadLocalUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class TanHuaService {

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;


    @DubboReference
    private UserLocationApi userLocationApi;


    @DubboReference
    private UserLikeApi userLikeApi;

    @Autowired
    private RedisTemplate<String ,String> redisTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;


    @Value("${tanhua.default.recommend.users}")
    private String defaultRecomment;




    /**
     *
     *查询今日佳人
     */
    public TodayBest queryToDayBest() {
        //1.获取操作的用户id
        Long userId = ThreadLocalUtils.getUserId();

        //2.根据用户id查询今日佳人,这个是操作mongoDB
        RecommendUser recommendUser = recommendUserApi.queryUserIdMaxScore(userId);

        if(recommendUser == null){
            recommendUser = new RecommendUser();
            recommendUser.setUserId(1L);
            recommendUser.setScore(90D);
        }
        //3.根据查询到的今日佳人的用户id查询用户详情
        Long toDayBestId = recommendUser.getUserId();//得到今日佳人的用户id
        UserInfo userInfo = userInfoApi.selectUserInfo(toDayBestId);//得到今日佳人详情


        TodayBest todayBest = TodayBest.init(userInfo, recommendUser);
        return todayBest;
    }


    /**分页查询推荐好友列表:
     *1.一开始查询RecommendUser表封装的PageResult的数据是recommendUser
     * 页面需要的PageResult的数据是ToDayBest
     * 一切的目的都是围绕把PageResult的数据是recommendUser转换为toDayBest
     *
     *
     *
     */
    public PageResult queryRecommendFriends(RecommendUserDto dto) {


        //1.获取当前用户id
        Long toUserId = ThreadLocalUtils.getUserId();

        //2.调用 recommendUserApi分页查询推荐好友
        //以下是以前写的错误的代码
        //PageResult pageResult = recommendUserApi.queryRecommendFriends(dto.getPage(), dto.getPagesize(), toUserId);
        List<RecommendUser> recommendUsers = recommendUserApi.queryRecommendFriends(dto.getPage(), dto.getPagesize(), toUserId);

        //3.获取所有推荐好友的数据列表
        //List<RecommendUser> recommendUsers = (List<RecommendUser>) pageResult.getItems();

        //4.如果recommendUsers为空，直接返回pageResult
        if(CollUtil.isEmpty(recommendUsers)){
            return new PageResult();
        }



        //5.获取全部推荐好友的用户id
        List<Long> userIds = CollUtil.getFieldValues(recommendUsers, "userId", Long.class);

        //6.构造查询条件，调用UserINfoApi批量查询推荐好友的用户详情
        UserInfo info = new UserInfo();
        info.setGender(dto.getGender());
        info.setAge(dto.getAge());


        //批量查询用户详情
        Map<Long, UserInfo> userInfoMap = userInfoApi.batchQueryUserInfo(userIds, info);  //键是用户id，值是用户详情

        List<TodayBest> todayBestList = new ArrayList<>();

        //7.遍历recommendUsers集合
        for (RecommendUser recommendUser : recommendUsers) {
            //获取每一个推荐好友的用户id
            Long userId = recommendUser.getUserId();
            //根据用户id查询用户详情
            UserInfo userInfo = userInfoMap.get(userId);

            if (userInfo != null) {
                TodayBest todayBest = TodayBest.init(userInfo, recommendUser);
                todayBestList.add(todayBest);
            }
        }


        PageResult pageResult = new PageResult(dto.getPage(), dto.getPagesize(),0,todayBestList);

        return pageResult;
    }


    /**
     * 根据id查看佳人详情
     * 这个id是当前用户要查看的用户的id
     * @param id
     * @return
     */
    public TodayBest queryToBestInfo(Long id) {
        //1.根据用户id查询用户详情
        UserInfo userInfo = userInfoApi.selectUserInfo(id);
        //2.根据当前用户的id，和当前用户要查看的用户id查询推荐人
        RecommendUser recommendUser = recommendUserApi.queryRecommendFriend(id,ThreadLocalUtils.getUserId());
        //3.构造返回值
        TodayBest todayBest = TodayBest.init(userInfo, recommendUser);
        return todayBest;
    }


    /**
     * 根据用户id查看用户设置，陌生人问题
     * @param userId
     * @return
     *
     */
    public String lookStrangerQuestions(Long userId) {
        Question question = questionApi.queryQuestion(userId);
         String strangerQuestions = question == null ?  "请说出石头为什么会这么硬?":question.getTxt();

         return strangerQuestions;
    }


    /**
     * 回复陌生人问题
     * @param userId
     * @param reply
     */
    public void replyStrangerQuestions(Long userId, String reply) {

        //这是发送给感兴趣的用户的信息数据格式
    /**  {
          "userId":1,”        当前操作用户的id
          "huanXinId":“hx1",  操作人的环信用户
           "nickname":"黑马小妹",     niciname：当前操作人昵称
           "strangerQuestion":"你喜欢去看蔚蓝的大海还是去爬巍峨的高山？",
           "reply":"我喜欢秋天的落叶，夏天的泉水，冬天的雪地，只要有你一切皆可~"
           }
     **/
        Long currentId = ThreadLocalUtils.getUserId();
        UserInfo userInfo = userInfoApi.selectUserInfo(currentId);//根据id获取用户详情，再获取用户昵称封装进map集合里

        //思路：构造一个map集合封装起来，再用工具转为JSON格式
        //1.构造数据
        Map map = new HashMap();
        map.put("userId", currentId);
        map.put("huanXinId", Constants. HX_USER_PREFIX+ currentId);
        map.put("nickname",userInfo.getNickname());
        map.put("strangerQuestion",lookStrangerQuestions(userId));//对方设置的问题
        map.put("reply",reply);//当前用户回答的问题
        //2.转为json
        String replyText = JSON.toJSONString(map);

        //3.调用环信服务回复陌生人问题,这是服务器操作java代码回复用户的
        //俩个参数，一个是要回复的对方环信id;另一个是要回复的内容
        Boolean result = huanXinTemplate.sendMsg(Constants.HX_USER_PREFIX + userId, replyText);
        if(!result ){
            throw new BusinessException(ErrorResult.error());
        }


    }

    /**
     * 查看卡片列表的推荐好友
     * @return
     */

    public List<TodayBest> lookCardsList() {
        //1.每次查询10条推荐用户，排除已喜欢过或已不喜欢过的用户
        List<RecommendUser> recommendUsers =recommendUserApi.lookCardsList(ThreadLocalUtils.getUserId(),10);

        //2.如果推荐的用户为空，构造默认推荐用户列表增强用户体验
        if(CollUtil.isEmpty(recommendUsers)){
            recommendUsers = new ArrayList<>();

            String[] userIds = defaultRecomment.split(",");
            for (String userId : userIds) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Convert.toLong(userId));
                recommendUser.setToUserId(ThreadLocalUtils.getUserId());
                recommendUser.setScore(RandomUtil.randomDouble(60, 90));
                recommendUsers.add(recommendUser);
            }
        }

        //3.批量获取推荐好友的用户id查询用户详情
        List<Long> userIds = CollUtil.getFieldValues(recommendUsers, "userId", Long.class);
        Map<Long, UserInfo> userInfoMap = userInfoApi.batchQueryUserInfo(userIds, null);
        //4.遍历recommendUsers集合，构造vo对象
        List<TodayBest> todayBests = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUsers) {
            Long id = recommendUser.getUserId();
            UserInfo userInfo = userInfoMap.get(id);

            if(userInfo != null){
                TodayBest todayBest = TodayBest.init(userInfo, recommendUser);
                todayBests.add(todayBest);
            }
        }

        return todayBests;
    }



    @Autowired
    private MessagesService messagesService;
    /**
     *右滑，喜欢
     */
    public void love(Long likeUserId) {

        //1.操作UserLike表，保存喜欢的数据到MongoDB
       Boolean result =  userLikeApi.saveOrUpdate(ThreadLocalUtils.getUserId(),likeUserId,true);//true代表喜欢
       //2.判断是否保存成功
        if(!result){
            throw new BusinessException(ErrorResult.error());
        }

        //3.操作redis，首先将喜欢的人从不喜欢集合中删除，再将喜欢的的人添加到喜欢的集合数据
        redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY + ThreadLocalUtils.getUserId(), likeUserId.toString());
        redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY + ThreadLocalUtils.getUserId(), likeUserId.toString());

        //4.判断是否互相喜欢
        Boolean like = isLike(likeUserId, ThreadLocalUtils.getUserId());

        if(like){
            //互相喜欢，添加为好友
            messagesService.addFriend(likeUserId);
        }
    }

    public Boolean isLike(Long userId,Long likeUserId ){
        //
        String key = Constants.USER_LIKE_KEY +userId;
        //判断对方的喜欢集合里是否有我的id
        return redisTemplate.opsForSet().isMember(key, likeUserId.toString());
    }


    /**
     * 左滑不喜欢
     * @param unLikeUserId
     */
    public void unLove(Long unLikeUserId) {
        //1.保存不喜欢的记录到数据库，操作的是mongoDb
        Boolean result = userLikeApi.saveOrUpdate(ThreadLocalUtils.getUserId(), unLikeUserId, false);

        if(!result){
            throw new BusinessException(ErrorResult.error());
        }


        //2.操作redis,在喜欢的集合中剔除名单，在不喜欢的集合中添加名单
        redisTemplate.opsForSet().remove(Constants.USER_LIKE_KEY+ThreadLocalUtils.getUserId(), unLikeUserId.toString());
        redisTemplate.opsForSet().add(Constants.USER_NOT_LIKE_KEY+ThreadLocalUtils.getUserId(), unLikeUserId.toString());



    }


    /**
     *
     *搜附近
     */
    public List<NearUserVo> queryNearUser(String gender, String distance) {
        //1.由于GeoJsonPoint不支持序列化，不可以在dubbo服务中传递
        //所以先调用api查询附近的人获取附近的人id
        Long userId = ThreadLocalUtils.getUserId();
        List<Long> ids = userLocationApi.queryNearUser(userId, Double.valueOf(distance));

        //2.判断api层返回的id集合是否为空,为空则返回一个空的集合
        if(CollUtil.isEmpty(ids)){
            return new ArrayList<>();
        }
        //3.根据附近的人的id查询他们的用户详情
        UserInfo userInfo = new UserInfo();
        userInfo.setGender(gender);//这是条件
        Map<Long, UserInfo> userInfoMap = userInfoApi.batchQueryUserInfo(ids, userInfo);
        //4.构造vo返回
        List<NearUserVo> vos = new ArrayList<>();

        for (Long id : ids) {
            if(id == ThreadLocalUtils.getUserId()){
                continue;
            }

            UserInfo nearUserInfo = userInfoMap.get(id);

            if(nearUserInfo != null){
                NearUserVo vo = NearUserVo.init(nearUserInfo);
                vos.add(vo);
            }

        }

        return vos;
    }
}
